package com.webex.ta.hydra.gui.execution;

import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-10-21
 * Time: 10:36:51
 */
public class Invoker {
    public static final Object LOCK = new Object();
    private static final AtomicBoolean FLUSHER_SCHEDULED = new AtomicBoolean(false);
    private static final Runnable flushQueue = new FlushQueue();
    private static final List<RunnableInfo> queue = new ArrayList<RunnableInfo>();

    public static ActionCallback invoke(Runnable runnable) {
        ActionCallback callback = new ActionCallback();
        synchronized (LOCK) {
            queue.add(new RunnableInfo(runnable, callback));
        }
        return callback;
    }

    private static void requestFlush() {
        if (FLUSHER_SCHEDULED.compareAndSet(false, true))
            SwingUtilities.invokeLater(flushQueue);
    }

    private static RunnableInfo pollNext() {
        synchronized (LOCK) {
            if (!queue.isEmpty()) {
                return queue.remove(0);
            }
            return null;
        }
    }

    private static class RunnableInfo {
        final Runnable runnable;
        final ActionCallback callback;

        public RunnableInfo(Runnable runnable, ActionCallback callback) {
            this.runnable = runnable;
            this.callback = callback;
        }
    }

    private static class FlushQueue implements Runnable {
        public void run() {
            FLUSHER_SCHEDULED.set(false);

            final RunnableInfo info = pollNext();

            if (info != null) {
                try {
                    info.runnable.run();
                    info.callback.setDone();
                } catch (Throwable t) {
                    // TODO log it
                }
            }
        }
    }
}
